#include "Includes.h"
#include "DRV_Main.h"
#include "DEV_Station.h"
#include "SVS_Station.h"
#include "APP_Charging.h"
#include "APP_Comm.h"
#include "OPP_Debug.h"
#include "DEV_Timer.h"

extern char *strStaDesc[];
extern char *strChgingDesc[];
extern char *strCommDesc[];
extern U16 HardFault;//硬件故障

enum EN_STA_STATE g_enStaState=STA_STATE_OFFLINE;//充电桩状态
enum EN_STA_CHGING_SUB_STATE g_enStaChgingSubState=STA_SUB_CHGING_STATE_PREPARA;//充电子状态
U8 expireStopChgFlag=0;

void ChgPrintInfoDelay(int timeout,char *tag)
{
    static U32 tick = 0;

    if(0 == tick){
        tick = OppTickCountGet();
    }else if(OppTickCountGet() - tick > timeout){
        DEBUG_LOG(DEBUG_MODULE_CHG, DLL_ERROR, "CHG[%s] run..........\r\n",tag);
        tick = 0;
    }
}

enum EN_STA_STATE StationStateGet(void)
{
    return g_enStaState;
}

int StationStateSet(enum EN_STA_STATE state)
{
    g_enStaState = state;
    DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"===>Station State is %s\r\n",strStaDesc[state]);
    return 0;
}

enum EN_STA_CHGING_SUB_STATE ChgSubStateGet(void)
{
    return g_enStaChgingSubState;
}

int ChgSubStateSet(enum EN_STA_CHGING_SUB_STATE state)
{
    g_enStaChgingSubState = state;
    DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"===>Chging SubState is %s\r\n",strChgingDesc[state]);
    return 0;
}

int startCheck(void)
{
    printf("=========>startCheck\r\n");
    return 0;
}
int stopCheck(void)
{
    printf("=========>stopCheck\r\n");
    return 0;
}

//远程停止充电或桩停止充电或车停止充电正常流程
int StopChgChkTimer(void *pParameter)
{
    DEBUG_LOG(DEBUG_MODULE_CHG, DLL_ERROR,"============>Stop Charge Check Timer expire!!!\r\n");
    ac_relay_set(0);
    if(StationStateGet()==STA_STATE_CHG)
    {
        expireStopChgFlag=1;
    }
    return 0;
}

void SendStopSignal(void)
{
    cp_duty_set(CP_12V_DUTY);
    if(StationStateGet()==STA_STATE_CHG)
    {
        DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Start APP_CHG_STOPCHG_CHK_TIMERID\r\n");
        TTimer_Start(APP_CHG_STOPCHG_CHK_TIMERID);
    }
}

int (*pstartFunc)()=startCheck;
int (*pstopFunc)()=stopCheck;
U8 checkGun=0;//延迟检查拔枪

//充电中子任务
void CHGINGLOOP(void)
{
    static enum EN_STA_CHGING_SUB_STATE lastStaChgingState=STA_SUB_CHGING_STATE_PREPARA;//充电子状态
    static U8 err=0,doPrepara=0;//0.故障检查 1.充电准备动作 2.等待车就绪 3.车就绪
    static U32 tick=0;
    //static U8 checkGun=0;//延迟检查拔枪

    if(STA_STATE_CHG != StationStateGet())
        return;

    //远程停止充电或桩停止充电或车停止充电正常流程
    if(TTimer_IsRunning(APP_CHG_STOPCHG_CHK_TIMERID))
    {
        if(GunStateGet()<GUN_PLUG_READY)
        {
            DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Stop APP_CHG_STOPCHG_CHK_TIMERID\r\n");
            TTimer_Stop(APP_CHG_STOPCHG_CHK_TIMERID);
        }
    }
    //车不就绪切换到充电完成或者发送停止信号后超时未监测到枪压
    if((checkGun && !CarIsReady()) || expireStopChgFlag)
    {
        DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Car Is Not Ready\r\n");
        if(ChgSubStateGet()!=STA_SUB_CHGING_STATE_CHGED)
        {
            ChgSubStateSet(STA_SUB_CHGING_STATE_CHGED);
        }
        else
        {
            StationStateSet(STA_STATE_IDLE);
            return;
        }
    }
    //状态变化
    if(lastStaChgingState != ChgSubStateGet())
    {
        DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>substate from %s to %s\r\n",strChgingDesc[lastStaChgingState],strChgingDesc[ChgSubStateGet()]);
        lastStaChgingState=ChgSubStateGet();
        //状态变化，准备工作清零
        if(ChgSubStateGet()!=STA_SUB_CHGING_STATE_PREPARA)
        {   
            doPrepara=0;
            //PREPARA阶段延迟10S做枪状态判断，其他状态实时做枪状态判断
            checkGun=1;
        }
        if(ChgSubStateGet()==STA_SUB_CHGING_STATE_CHGING)
        {
            BillStart(GunNum);
        }
        if(ChgSubStateGet()==STA_SUB_CHGING_STATE_CHGED)
        {
            BillStop(GunNum);
        }
        tick=0;
    }
    
    switch (ChgSubStateGet())
    {
        case STA_SUB_CHGING_STATE_PREPARA:
            if(tick==0)
            {
                tick=OppTickCountGet();
                checkGun=0;
                doPrepara=0;
            }
            //延迟10s做拔枪判断
            if(OppTickCountGet()-tick > CHGING_CHECKGUN_DELAY)
            {
                checkGun=1;
            }
            //故障检查
            if(doPrepara==0)
            {
                //故障检查通过，do next
                if(pstartFunc!=NULL)
                    err=pstartFunc();
                if(err==0)
                    doPrepara=1;
            }            
            //充电准备动作
            else if(doPrepara==1)
            {
                cp_duty_set(CP_32A_DUTY);
                doPrepara=2;
            }
            else
            {
                if(CarIsReady())
                {
                    DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Car Is Ready\r\n");
                    ac_relay_set(1);
                    ChgSubStateSet(STA_SUB_CHGING_STATE_CHGING);
                    doPrepara=3;
                }
            }
            break;
        case STA_SUB_CHGING_STATE_CHGING:
            ChgPrintInfoDelay(5000,"Chging...");
            //车充满电
            if(CarIsFull())
            {
                DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Car Is Full\r\n");
                ChgSubStateSet(STA_SUB_CHGING_STATE_CHGED);
            }
            break;
        case STA_SUB_CHGING_STATE_CHGED:
            ChgPrintInfoDelay(5000,"Chging Over");
            //清除超时标志位
            if(expireStopChgFlag)
            {
                expireStopChgFlag=0;
                StationStateSet(STA_STATE_IDLE);
            }
            break;
        default:
            break;
    }

}
//充电主任务
void CHGLOOP(void)
{
    static enum EN_STA_STATE lastStaState=STA_STATE_OFFLINE,recordLastStaState=STA_STATE_OFFLINE;//充电桩状态
    static enum EN_COMM_FSM lastCommFsm=COMM_FSM_INIT;
    static U8 err=0, abnormalAction=0,abnormalCheck=0;
    static U16 lastHardFault=0;//硬件故障

    //桩状态变化
    if(lastStaState!=StationStateGet())
    {
        //当前状态充电,上一次状态不是充电，充电子状态要是准备充电
        if(StationStateGet()==STA_STATE_CHG && lastStaState!=STA_STATE_CHG)
            ChgSubStateSet(STA_SUB_CHGING_STATE_PREPARA);
        recordLastStaState=lastStaState;
        lastStaState=StationStateGet();
        abnormalAction=0;
        abnormalCheck=0;
        //上报监控状态
        CommMonitorRpt(NULL);
    }
    //通讯状态发生变化
    if(lastCommFsm != CommFsmGet())
    {
        lastCommFsm=CommFsmGet();
        //通讯故障未登录服务器
        if(CommFsmGet()!=COMM_FSM_READY)
        {
            //空闲或已充电完成切换到离线状态
            if((StationStateGet()==STA_STATE_IDLE) || 
                (StationStateGet()==STA_STATE_CHG && ChgSubStateGet()==STA_SUB_CHGING_STATE_CHGED))
                StationStateSet(STA_STATE_OFFLINE);
        }
        //通讯恢复且已登录服务器
        else
        {
            if(recordLastStaState == STA_STATE_CHG && GunIsPlugin())
            {
                StationStateSet(STA_STATE_CHG);
            }
            else
            {
                StationStateSet(STA_STATE_IDLE);
            }
        }
    }
    //故障状态发生变化
    if(lastHardFault!=HardFault)
    {
        if(HardFault!=0)
        {
            StationStateSet(STA_STATE_ABNORMAL);
        }
        else
        {
            if(recordLastStaState == STA_STATE_CHG && GunIsPlugin())
            {
                StationStateSet(STA_STATE_CHG);
            }
            else
            {
                StationStateSet(STA_STATE_IDLE);
            }
        }
        lastHardFault=HardFault;
    }
    switch (StationStateGet())
    {
        case STA_STATE_OFFLINE:
        case STA_STATE_ABNORMAL:
            if(abnormalCheck==0)
            {
                if(pstopFunc!=NULL)
                    err=pstopFunc();
                if(err==0)
                    abnormalCheck=1;
            }
            if(abnormalCheck==1 && abnormalAction==0)
            {
                ac_relay_set(1);
                cp_duty_set(CP_12V_DUTY);
                abnormalAction=1;
            }
            break;
        case STA_STATE_IDLE:
            if(CarIsReady() && IsCardSwipAction())
            {
                DEBUG_LOG(DEBUG_MODULE_CHG, DLL_INFO,"============>Active Request chg\r\n");
                CommActiveStartChgReq(NULL);
            }
            break;
        case STA_STATE_CHG:
            CHGINGLOOP();
            break;
        default:
            break;
    }
}



